
let user = {
    id: 10086 ,
    name: '移动用户'
}

// Object.prototype.propertyIsEnumerable( name )
// 判断指定的属性在指定对象中是否是 可枚举的(enumerable)
console.log( user.propertyIsEnumerable( 'id' ) );
console.log( user.propertyIsEnumerable( 'name' ) );

// Object.defineProperty( object , name , descriptor )
// 为 object 对象定义 name 属性，并设置该属性的描述信息

const descriptor = {
    // 用 value 描述新定义的 property 的值 (取值可以是JavaScript中任意类型)
    value: 'hello',
    // 用 enumerable 来描述新定义的 property 是否 可枚举
    enumerable: true,
    // 用 writable 来描述新定义的 property 是否 可修改
    writable: true ,
    // 用 configurable 来描述新定义的 property 是否 可配置
    configurable: true
}
// 为对象定义 property
Object.defineProperty( user , 'password' , descriptor );

console.log( user.password );
console.log( user.propertyIsEnumerable( 'password' ) );

user.password = 'abc123';
console.log( user.password );

// 当且仅当 configurable 为 true 时 password 才可以被配置( 比如 删除该属性 或 修改该属性的 descriptor )
delete user.password;
console.log( user.password );

// 若 user 中本就存在 password 属性则修改其 descriptor (如果可以配置的话)
Object.defineProperty( user , 'password' , { 
    value: function(){
        return 'xyz789';
    } , 
    // configurable 为 false 时表示不可配置(即不可删除该属性也不可修改该属性的描述器)
    configurable: false , 
    // enumerable 为 false 表示属性是不可被枚举的
    enumerable: false , 
    // writable 为 false 表示属性是不可被赋值的
    writable: false 
} );

console.log( user.password() );
delete user.password;
console.log( user.password() );

user.password = 'abc123';
console.log( user.password() );